package com.heimdallr.rbac.permission.service.impl;

import com.heimdallr.config.ShiroConfig;
import com.heimdallr.rbac.permission.dao.PermissionDao;
import com.heimdallr.rbac.permission.entity.MenuEntity;
import com.heimdallr.rbac.permission.entity.PermissionEntity;
import com.heimdallr.rbac.permission.entity.RoleEntity;
import com.heimdallr.rbac.permission.entity.UserEntity;
import com.heimdallr.rbac.permission.service.IPermissionService;
import com.heimdallr.rbac.user.service.UserService;
import com.heimdallr.util.AppUtils;
import com.heimdallr.util.cache.CachePool;
import com.heimdallr.util.cache.LocalCache;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


/**
 * @author panxl
 */
@Service
public class PermissionServiceImpl implements IPermissionService {
	
	@Autowired
	private PermissionDao permissionDao;
    @Autowired
    private UserService userService;


    /** for permission page **/
    @Override
    public List<PermissionEntity> getPermissionListForPage(Map<String, String> paraMap){

        return permissionDao.getPermissionListForPage(paraMap);
    }

    @Override
    public boolean addPermissionEntity(PermissionEntity entity){
        return permissionDao.savePermissionEntity(entity);
    }


    /** for role page **/
    @Override
    public List<RoleEntity> getRoleListForPage(Map<String, String> paraMap){

        return permissionDao.getRoleListForPage(paraMap);
    }


    @Override
    public RoleEntity getRoleEntityById(int id){

        return permissionDao.getRoleEntityById(id);
    }

    @Override
    public boolean editRoleHasMenu(String roleId, String[] menuIds){


        RoleEntity roleEntity = getRoleEntityById(Integer.parseInt(roleId));
        List<MenuEntity> menuEntityList = new ArrayList<>();

        for(String menuId:menuIds){
            MenuEntity menuEntity = permissionDao.getMenuEntityById(Integer.parseInt(menuId));
            menuEntityList.add(menuEntity);
        }//end foreach

        roleEntity.setMenuEntityList(menuEntityList);
        roleEntity.setMenuIds(menuEntityList.stream().mapToInt(MenuEntity::getId).collect(ArrayList::new,ArrayList::add,ArrayList::addAll));
        permissionDao.saveRoleEntity(roleEntity);

        return true;
    }

    @Override
    public boolean editRoleHasPerms(String roleId, String[] permIds) {

        RoleEntity roleEntity = permissionDao.getRoleEntityById(Integer.parseInt(roleId));

        List<PermissionEntity> permissionEntityList = new ArrayList<>();

        for(String permId:permIds){
            int permissionId = Integer.parseInt(permId);
            PermissionEntity permissionEntity = permissionDao.getPermissionEntityById(permissionId);
            permissionEntityList.add(permissionEntity);
        }//end foreach

        roleEntity.setPermissionEntityList(permissionEntityList);
        roleEntity.setPermissionIds(permissionEntityList.stream().mapToInt(PermissionEntity::getId).collect(ArrayList::new,ArrayList::add,ArrayList::addAll));
        permissionDao.saveRoleEntity(roleEntity);

        return true;
    }




    @Override
    public List<RoleEntity> getAllRoleEntity(){

        return permissionDao.getAllRoles();
    }

    @Override
    public List<PermissionEntity> getAllPermissionEntity(){

        return permissionDao.getAllPermissionEntity();
    }


    /**
     * 以下部分为菜单的获取
     * @param userName
     * @return
     */
    @Override
    public List<MenuEntity> getMenuList(String userName){

        LocalCache localCache = CachePool.getInstance().getCache(CachePool.cacheKind.dataCache);
        String hour = new SimpleDateFormat("yyyyMMdd HH").format(new GregorianCalendar().getTime());
        String key = (Thread.currentThread().getStackTrace()[1].getMethodName()+"_"+userName+"_"+hour).hashCode()+"";

        if(localCache.containsKey(key)){
            return (List<MenuEntity>) localCache.getValue(key);
        }else{

            UserEntity userEntity = userService.getUserEntityByUserName(userName);

            List<MenuEntity> menuList = new ArrayList<>();

            Set<Integer> menuIds = new HashSet<>();

            if(userEntity!=null&&userEntity.getGroupEntity()!=null&&
                    userEntity.getGroupEntity().getRoleEntityList()!=null&&!userEntity.getGroupEntity().getRoleEntityList().isEmpty()){

                List<RoleEntity> roleEntityList = userEntity.getGroupEntity().getRoleEntityList();

                for(RoleEntity roleEntity:roleEntityList){

                    List<MenuEntity> menuEntityList = roleEntity.getMenuEntityList();


                    if(menuEntityList!=null&&!menuEntityList.isEmpty()){


                        for(MenuEntity menuEntity:menuEntityList){

                            menuIds.add(menuEntity.getId());

                            if(menuEntity.getChildren()!=null&&!menuEntity.getChildren().isEmpty()){

                                menuIds.addAll(menuEntity.getChildren().stream().map(MenuEntity::getId).collect(Collectors.toList()));

                            }// end if  menuEntity.getChildren()!=null

                        }// end foreach MenuEntity


                    }// end menuEntityList!=null


                }// end foreach RoleEntity


            }// end userEntity whole is not null

            if(!menuIds.isEmpty()){
                menuList.addAll(menuIds.stream().map(menuId -> permissionDao.getMenuEntityById(menuId)).collect(Collectors.toList()));
            }

            for(MenuEntity entity:menuList){
                AppUtils.buildTree(menuList,entity);
            }

            List<MenuEntity> reList = menuList.stream().filter(entity -> entity.getPid() == null||entity.getPid()==0).collect(Collectors.toList());

            localCache.putValue(key,reList);

            return reList;
        }

    }

    @Override
    public List<MenuEntity> getAllMenu(){


        List<MenuEntity> menuList = permissionDao.getAllMenuList();

        for(MenuEntity entity:menuList){
            AppUtils.buildTree(menuList,entity);
        }

        return menuList.stream().filter(entity -> entity.getPid() == null||entity.getPid()==0).collect(Collectors.toList());

    }



}
